// EncodingStream.h : Declaration of the CEncodingStream

#ifndef __ENCODINGSTREAM_H_
#define __ENCODINGSTREAM_H_

#include "resource.h"       // main symbols
#include "oaidl.h"
#include "Encoder.h"

/////////////////////////////////////////////////////////////////////////////
// CEncodingStream
class ATL_NO_VTABLE CEncodingStream : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CEncodingStream, &CLSID_EncodingStream>,
	public ISupportErrorInfo,
	public IDispatchImpl<IEncodingStream, &IID_IEncodingStream, &LIBID_BASE64Lib>,
	public IStream
{
public:
	CEncodingStream()
		:m_pTargetStream(0)
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_ENCODINGSTREAM)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CEncodingStream)
	COM_INTERFACE_ENTRY(IEncodingStream)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(ISupportErrorInfo)
	COM_INTERFACE_ENTRY(IStream)
END_COM_MAP()
// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);

// IEncodingStream
public:
	STDMETHOD(open)(BSTR sFileName,BOOL bWriteWideChars);
// IStream
	STDMETHOD(Seek)(_LARGE_INTEGER dlibMove, ULONG dwOrigin, _ULARGE_INTEGER * plibNewPosition)
	{
		if (plibNewPosition == NULL)
			return E_POINTER;
			
		return E_NOTIMPL;
	}
	STDMETHOD(SetSize)(_ULARGE_INTEGER libNewSize)
	{
		return E_NOTIMPL;
	}
	STDMETHOD(CopyTo)(IStream * pstm, _ULARGE_INTEGER cb, _ULARGE_INTEGER * pcbRead, _ULARGE_INTEGER * pcbWritten)
	{
		if (pcbRead == NULL)
			return E_POINTER;
			
		if (pcbWritten == NULL)
			return E_POINTER;
			
		return E_NOTIMPL;
	}
	STDMETHOD(Commit)(ULONG grfCommitFlags)
	{
		return E_NOTIMPL;
	}
	STDMETHOD(Revert)()
	{
		return E_NOTIMPL;
	}
	STDMETHOD(LockRegion)(_ULARGE_INTEGER libOffset, _ULARGE_INTEGER cb, ULONG dwLockType)
	{
		return E_NOTIMPL;
	}
	STDMETHOD(UnlockRegion)(_ULARGE_INTEGER libOffset, _ULARGE_INTEGER cb, ULONG dwLockType)
	{
		return E_NOTIMPL;
	}
	STDMETHOD(Stat)(tagSTATSTG * pstatstg, ULONG grfStatFlag)
	{
		if (pstatstg == NULL)
			return E_POINTER;
			
		return E_NOTIMPL;
	}
	STDMETHOD(Clone)(IStream * * ppstm)
	{
		if (ppstm == NULL)
			return E_POINTER;
			
		return E_NOTIMPL;
	}
// ISequentialStream
	   STDMETHOD(Read)( 
            /* [length_is][size_is][out] */ void *pv,
            /* [in] */ ULONG cb,
            /* [out] */ ULONG *pcbRead);
        
       STDMETHOD(Write)( 
            /* [size_is][in] */ const void *pv,
            /* [in] */ ULONG cb,
            /* [out] */ ULONG *pcbWritten);



private:
	//holds the stream to which encoded data is being written.
	//	probably move to base class
	IStream * m_pTargetStream;
	char m_pcInputBlock[3];
	int m_iBlockPosition;

	CEncoder m_Encoder;
	
};

#endif //__ENCODINGSTREAM_H_
